/**
  * \file genI3MiddleBoxConf.cpp
  * \brief This program generates the configuration text that needs to be added 
  * to the various OCALA configuration files in order to support i3 middleboxes.
  */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "common.h"
#include "I3Id.h"
extern "C" {
#   include "i3_id.h"
#   include "i3_trigger.h"
#   include "i3_client.h"
#   include "i3_client_id.h"
#   include "../aeshash/aes.h"
}

//#define TESTING 1

void printUsage () {

    printf ("\n./genI3MiddleBoxConf <endhostName> <middleboxName> <ocdId>\n"
            "\t\t endhostName eg: hello.pli3\n"
            "\t\t middleboxName eg: myMiddleBox.pli3\n"
            "\t\t ocdId eg: pli3>\n\n"
        );

}

/**
  * Example Usage Scenario:  Suppose you want to run a webserver on your machine, say hello.pli3.
  * You want all the traffic to hello.pli3 to go through a particular middlebox.
  * This means that you need to insert a stack of triggers for hello.pli3.  On the machine running the middlebox,
  * you need to insert the second trigger in the above stack.
  * This program gives you the configuration file snippets needed for this purpose.
  */
int main (int argc, char* argv[]) {

    if (argc < 4) {
        printUsage ();
        exit (-1);
    }

    // The end host's name. For example: hello.pli3
    char endHostName [MAX_URL_LEN];
    if (strlen (argv[1]) > MAX_URL_LEN - 1) {
        printf ("ERROR: The specified endhost name is too long.  Please specify a name with less than %d characters.\n", 
                    MAX_URL_LEN - 1
                );
        exit (-1);
    }
    strcpy (endHostName, argv[1]);

    // For example: myMiddleBox.pli3
    char middleBoxName [MAX_URL_LEN];
    if (strlen (argv[1]) > MAX_URL_LEN - 1) {
        printf ("ERROR: The specified middlebox name is too long.  Please specify a name with less than %d characters.\n", 
                    MAX_URL_LEN - 1
                );
        exit (-1);
    }
    strcpy (middleBoxName, argv[2]);

    // For example: pli3
    char ocdId [MAX_PARAM_LEN];
    if (strlen (argv[1]) > MAX_PARAM_LEN - 1) {
        printf ("ERROR: The specified ocd id is too long.  Please specify an ocd id with less than %d characters.\n", 
                    MAX_PARAM_LEN - 1
                );
        exit (-1);
    }
    strcpy (ocdId, argv[3]);


   
    printf ("Generating middle box configuration for endhost %s, middlebox %s, ocdId %s...\n", endHostName, middleBoxName, ocdId);
   
    aeshash_init ();

    // The id of the end host's name, found by taking a hash of its name.
    ID endHostId;
    char endHostIdStr[sizeof (ID) * 2 + 2];
    I3Id::hash_URL_on_ID( endHostName, &endHostId);
   

    ID endHostPrivId;
    ID middleBoxPrivId;
    char endHostPrivIdStr[sizeof(ID) * 2 + 2];
    char middleBoxPrivIdStr[sizeof(ID) * 2 + 2];

#ifdef TESTING
    strcpy (endHostPrivIdStr, "6210bad76b9b18f12ca59c4b34091b23c1a254c08cf91ae14206a0219a8e62fd");
    strcpy (middleBoxPrivIdStr, "12f059a9faa16961702708df7bdcd282097285fab9be43316dd3f6796869ca7a");
    sscanf_i3_id (endHostPrivIdStr, &endHostPrivId);
    sscanf_i3_id (middleBoxPrivIdStr, &middleBoxPrivId);
    printf ("endHostPrivIdStr = %s.\n", sprintf_i3_id (endHostPrivIdStr, &endHostPrivId));
    printf ("middleBoxPrivIdStr = %s.\n", sprintf_i3_id (middleBoxPrivIdStr, &middleBoxPrivId));
#else

    // generate random middle box private id and end host private id.
    I3Id::get_random_ID (&middleBoxPrivId);
    I3Id::get_random_ID (&endHostPrivId);

    cl_set_private_id (&endHostPrivId);
#endif

    cl_set_private_id (&middleBoxPrivId);

    printf ("Copy the following XML snippet to the myNames.xml file on your end host:\n\n");
    printf (    "<MyName \n"
                "\tname=\"%s\"\n"
                "\tocdId=\"%s\"\n"
                "\tactive=\"true\"\n"
                "\ti3TriggerType=\"public\"\n"
                "\ti3Key=\"\"\n"
                "\ti3IdStack=\"%s,%s\"\n"
                "\ti3NameStack=\"%s,\"\n"
                "/>\n\n"
                ,
                endHostName,
                ocdId,
                sprintf_i3_id (middleBoxPrivIdStr, &middleBoxPrivId), sprintf_i3_id(endHostPrivIdStr, &endHostPrivId),
                middleBoxName
            );
    printf (    "<MyName \n"
                "\tname=\"notused\"\n"
                "\tocdId=\"%s\"\n"
                "\tactive=\"true\"\n"
                "\ti3Id=\"%s\"\n"
                "\ti3TriggerType=\"private\"\n"
                "/>\n\n"
                ,
                ocdId,
                sprintf_i3_id (endHostPrivIdStr, &endHostPrivId)
            );


    update_id_id(&endHostId, &middleBoxPrivId, CL_TRIGGER_CFLAG_R_CONSTRAINT | CL_TRIGGER_CFLAG_PRIVATE);


    printf ("Copy the following XML snippet to the myNames.xml file on your middlebox:\n\n");
    printf (    "<MyName \n"
                "\tname=\"notused\"\n"
                "\tocdId=\"%s\"\n"
                "\tactive=\"true\"\n"
                "\ti3Id=\"%s\"\n"
                "\ti3TriggerType=\"private\"\n"
                "/>\n\n"
                ,
                ocdId,
                sprintf_i3_id (middleBoxPrivIdStr, &middleBoxPrivId)
            );




}
